package com.carbonspark.auth.domain.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.carbonspark.auth.common.entity.PageResult;
import com.carbonspark.auth.common.enums.AuthUserStatusEnum;
import com.carbonspark.auth.common.enums.IsDeletedFlagEnum;
import com.carbonspark.auth.domain.constants.AuthConstant;
import com.carbonspark.auth.domain.convert.AuthUserBOConverter;
import com.carbonspark.auth.domain.entity.AuthUserBO;
import com.carbonspark.auth.domain.redis.RedisUtil;
import com.carbonspark.auth.domain.service.AuthUserDomainService;
import com.carbonspark.auth.infrt.basic.entity.*;

import com.carbonspark.auth.infrt.basic.service.*;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private AuthPermissionService authPermissionService;

    private String salt = "mezhate";

    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    private static final String LOGIN_PREFIX = "loginCode";


    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        Integer count = authUserService.update(authUser);
        return count > 0;
    }


    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        Integer count = authUserService.update(authUser);
        //有任何的更新，都要与缓存进行同步的修改
        return count > 0;
    }








    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        // 1. 校验用户名是否已存在
        AuthUser existAuthUser = new AuthUser();
        existAuthUser.setUserName(authUserBO.getUserName());
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if (!existUser.isEmpty()) {
            throw new RuntimeException("用户已注册");
        }

        // 2. 插入用户信息到数据库
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());     // 设置用户状态为“启用”
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode()); // 标记未删除
        Integer count = authUserService.insert(authUser);
        if (count <= 0) {
            throw new RuntimeException("用户注册失败");
        }

        // 3. 分配默认角色（例如：normal_user）
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER); // 查询默认角色
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        if (roleResult == null) {
            throw new RuntimeException("默认角色不存在");
        }
        Long roleId = roleResult.getId();
        Long userId = authUser.getId(); // 获取新注册用户的ID

        // 4. 建立用户-角色关联关系
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setRoleId(roleId);
        authUserRole.setUserId(userId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);

        // 5. 查询该角色对应的权限列表
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId)
                .collect(Collectors.toList());
        List<AuthPermission> permissionList = authPermissionService.queryByRoleList(permissionIdList);

        // 6. 将角色和权限信息存储到 Redis
        // 角色键：auth.role:{userId}
        String roleKey = redisUtil.buildKey("auth.role", userId.toString());
        List<String> roleKeys = Collections.singletonList(roleResult.getRoleKey());
        redisUtil.set(roleKey, new Gson().toJson(roleKeys));

        // 权限键：auth.permission:{userId}
        String permissionKey = redisUtil.buildKey("auth.permission", userId.toString());
        List<String> permissionKeys = permissionList.stream()
                .map(AuthPermission::getPermissionKey)
                .collect(Collectors.toList());
        redisUtil.set(permissionKey, new Gson().toJson(permissionKeys));

        return true;
    }






    @Override
    public SaTokenInfo doLogin(String username, String password) {
        // 1. 根据用户名查询用户信息
        AuthUser authUser = authUserService.queryByName(username);
        if (authUser == null) {
            throw new RuntimeException("用户不存在");
        }

        // 2. 验证密码
        if (!password.equals(authUser.getPassword())) {
            throw new RuntimeException("密码错误");
        }




        // 5. 执行登录操作，生成 Token
        StpUtil.login(username);



        // 7. 返回 Token 信息（前端需保存 Token）
        return StpUtil.getTokenInfo();
    }

    @Override
    public PageResult<AuthUserBO> getUserList(AuthUserBO authUserBO) {
        PageResult<AuthUserBO> pageResult = new PageResult<>();
        //设置分页结果的当前页码和每页大小
        pageResult.setPageNo(authUserBO.getPageNo());
        pageResult.setPageSize(authUserBO.getPageSize());

        //计算起始位置start
        int start = (authUserBO.getPageNo()-1)* authUserBO.getPageSize();
        //查询符合条件的总记录数
        int count = authUserService.countByCondition();

        // 5. 如果总记录数为 0，直接返回空的分页结果

        // 6. 根据起始位置和每页大小查询任务列表
        List<AuthUser> authUsers = authUserService.selectUserListResult(start, authUserBO.getPageSize());

        // 7. 将任务实体列表转换为业务对象列表
        List<AuthUserBO> authUserBOS = AuthUserBOConverter.INSTANCE.convertEntityListToBOList(authUsers);

        // 8. 将转换后的业务对象列表设置到分页结果中
        pageResult.setRecords(authUserBOS);

        // 9. 将总记录数设置到分页结果中
        pageResult.setTotal(count);

        // 10. 返回最终的分页结果
        return pageResult;
    }

    @Override
    public PageResult<AuthUserBO> selectUserList(AuthUserBO authUserBO) {
        PageResult<AuthUserBO> pageResult = new PageResult<>();
        //设置分页结果的当前页码和每页大小
        pageResult.setPageNo(authUserBO.getPageNo());
        pageResult.setPageSize(authUserBO.getPageSize());

        //计算起始位置start
        int start = (authUserBO.getPageNo()-1)* authUserBO.getPageSize();
        //查询符合条件的总记录数
        int count = authUserService.countByCondition();

        // 5. 如果总记录数为 0，直接返回空的分页结果

        // 6. 根据起始位置和每页大小查询任务列表
        List<AuthUser> authUsers = authUserService.selectUserList(start, authUserBO.getPageSize());

        // 7. 将任务实体列表转换为业务对象列表
        List<AuthUserBO> authUserBOS = AuthUserBOConverter.INSTANCE.convertEntityListToBOList(authUsers);

        // 8. 将转换后的业务对象列表设置到分页结果中
        pageResult.setRecords(authUserBOS);

        // 9. 将总记录数设置到分页结果中
        pageResult.setTotal(count);

        // 10. 返回最终的分页结果
        return pageResult;
    }

    @Override
    public AuthUserBO getUserInfo(String loginId) {

        AuthUser authUser = authUserService.queryByName(loginId);


        return AuthUserBOConverter.INSTANCE.convertEntityToBO(authUser);
    }
}
